import json
import os
import shutil
from urllib import request
import tornado
from tornado import gen
from tornado import web

import sys
sys.path.append("..")

from .base import BaseHandler
from utils.pathutil import PathBuilder
from utils.dbutil import MySQLConnection
from utils.dockerutil import VirtualEnvUtil
from utils.jsonresult import JsonResult, json_result_encoder

class VirtualEvnHandler(BaseHandler):
    @web.authenticated
    @gen.coroutine
    def get(self):
        error = ""
        user = self.get_current_user()
        env_name = self.get_argument("envname", "")
    
        # 检查该容器服务是否已经存在
        conn = MySQLConnection.get_connection()
        try:
            with conn.cursor() as cursor:
                sql = "select imagename, envname, virtualenv.description as envdesc, image.description as imagedesc \
                    from virtualenv inner join image on virtualenv.imageid=image.imageid where envname='{}'"
                cursor.execute(sql.format(env_name))
                env_info = cursor.fetchone()
                if not env_info:
                    error = '无效的虚拟环境'
        finally:
            conn.close()
        
        self.render("virtualenv.html", user=user, menu_tag=envname_map.get(env_name, 0), env_info=env_info,  error=error)


    @web.authenticated
    @gen.coroutine
    def post(self):
        user = self.get_current_user()
        account_name = user['accountname']
        
        request_data = json.loads(self.request.body.decode())
        operation = request_data.get('operation')
        operand = request_data.get('operand')

        json_result = JsonResult()

        call_func = dispatch_map.get(operation)
        if call_func is None:
            json_result.message = '无效的操作'
        else:
            call_func(account_name, operand, json_result)
        
        self.write(json.dumps(json_result, ensure_ascii=True, default=json_result_encoder))
        self.finish() 

    @staticmethod
    def ensure_service(account_name, operand, json_result):
        env_name = operand['envName']

        # 获取该虚拟环境对应的映像、端口、装载目录等信息
        conn = MySQLConnection.get_connection()
        try:
            with conn.cursor() as cursor:
                sql = "select imagename, ports, mounts, params from virtualenv inner join image on virtualenv.imageid=image.imageid where envname='{}'"
                cursor.execute(sql.format(env_name))
                env_info = cursor.fetchone()
                if not env_info:
                    json_result.success = False
                    json_result.message = '无效的虚拟环境'
                    return
        finally:
            conn.close()
        
        image_name = env_info['imagename']
        service_name = VirtualEnvUtil.build_virtual_env_service_name(account_name, image_name)
        image_full_name = VirtualEnvUtil.get_image_full_name(image_name) 
        service_exists = VirtualEnvUtil.service_exists(service_name)
        url = ""

        # 如果服务不存在，则启动服务
        if not service_exists:
            # 提取端口信息
            ports = []
            if env_info['ports']:
                for port in env_info['ports'].split(','):
                    ports.append(int(port))

            # 提取目录映射信息
            root_path = PathBuilder.get_virtual_env_dir_for_student(account_name)
            mounts = []
            if env_info['mounts']:
                for mount in env_info['mounts'].split(','):
                    source, target = mount.split(':')
                    # 创建原始目录(如果不存在)
                    full_source_path = os.path.join(root_path, source)
                    if not os.path.exists(full_source_path):
                        os.makedirs(full_source_path)

                    mounts.append({'source':full_source_path, 'target':target})
            
            # 提取参数信息
            params = []
            if env_info['params']:
                params = env_info['params'].split(',')

            result = VirtualEnvUtil.create_service(service_name, image_full_name, ports, mounts, params)
            if not result:
                json_result.success = False
                json_result.message = '创建服务失败'
        else:
            # 检查服务的就绪状态，如果已经就绪，则直接返回虚拟环境的URL
            _, port = VirtualEnvUtil.get_service_state_and_port(service_name)
            if port:
                url = "http://{}:{}".format(tornado.options.options.docker_swarm_manager_ip, port)
        
        json_result.data = {'service_name':service_name, 'url': url}
        
        
    @staticmethod
    def check_env_ready(account_name, operand, json_result):
        service_name = operand['serviceName']
        _, port = VirtualEnvUtil.get_service_state_and_port(service_name)
        if port:
            url = "http://{}:{}".format(tornado.options.options.docker_swarm_manager_ip, port)
            req = request.Request(url)
            try:
                res = request.urlopen(req)
                res.close()
                json_result.data = {'url':url}
            except:
                json_result.data = {'url': ''}


envname_map = {
    'javase' : 31,
    'javaweb' : 32
}

dispatch_map = {
    'ensure_service' : VirtualEvnHandler.ensure_service,
    'check_env_ready' : VirtualEvnHandler.check_env_ready
}

default_handlers = [
    (r'/virtualenv', VirtualEvnHandler),
]